Next: Examples of Catch, Up: Nonlocal Exits [Contents][Index]
catch and throwMost control constructs affect only the flow of control within
the construct itself. The function throw is the
exception to this rule of normal program execution: it performs a
nonlocal exit on request. (There are other exceptions, but they
are for error handling only.) throw is used inside a
catch, and jumps back to that catch.
For example:
(defun foo-outer ()
(catch 'foo
(foo-inner)))
(defun foo-inner ()
…
(if x
(throw 'foo t))
…)
The throw form, if executed, transfers control
straight back to the corresponding catch, which
returns immediately. The code following the throw is
not executed. The second argument of throw is used
as the return value of the catch.
The function throw finds the matching
catch based on the first argument: it searches for a
catch whose first argument is eq to the
one specified in the throw. If there is more than
one applicable catch, the innermost one takes
precedence. Thus, in the above example, the throw
specifies foo, and the catch in
foo-outer specifies the same symbol, so that
catch is the applicable one (assuming there is no
other matching catch in between).
Executing throw exits all Lisp constructs up to
the matching catch, including function calls. When
binding constructs such as let or function calls are
exited in this way, the bindings are unbound, just as they are
when these constructs exit normally (see Local Variables).
Likewise, throw restores the buffer and position
saved by save-excursion (see Excursions), and the narrowing
status saved by save-restriction. It also runs any
cleanups established with the unwind-protect special
form when it exits that form (see Cleanups).
The throw need not appear lexically within the
catch that it jumps to. It can equally well be
called from another function called within the
catch. As long as the throw takes place
chronologically after entry to the catch, and
chronologically before exit from it, it has access to that
catch. This is why throw can be used in
commands such as exit-recursive-edit that throw back
to the editor command loop (see Recursive
Editing).
Common Lisp note: Most other versions of Lisp, including Common Lisp, have several ways of transferring control nonsequentially:
return,return-from, andgo, for example. Emacs Lisp has onlythrow. The cl-lib library provides versions of some of these. See Blocks and Exits in Common Lisp Extensions.
catch establishes a return point for the
throw function. The return point is
distinguished from other such return points by
tag, which may be any Lisp object except
nil. The argument tag is evaluated
normally before the return point is established.
With the return point in effect, catch
evaluates the forms of the body in textual order.
If the forms execute normally (without error or nonlocal
exit) the value of the last body form is returned from the
catch.
If a throw is executed during the execution
of body, specifying the same value tag,
the catch form exits immediately; the value it
returns is whatever was specified as the second argument of
throw.
The purpose of throw is to return from a
return point previously established with catch.
The argument tag is used to choose among the
various existing return points; it must be eq to
the value specified in the catch. If multiple
return points match tag, the innermost one is
used.
The argument value is used as the value to
return from that catch.
If no return point is in effect with tag tag,
then a no-catch error is signaled with data
(tag value).
Next: Examples of Catch, Up: Nonlocal Exits [Contents][Index]